//package miniparser;
//import minijava.*;
//import java.util.*;
//import System.IO.*;

public class CFGGenerator : MinijavaVisitor, Constants {
    TextWriter writer;
    public CFGGenerator(String filename) {
        try {
            writer = new StreamWriter(filename + ".cfg.mp");
        }
        catch (IOException ioe) {
            Console.WriteLine(ioe);
        }
    }
    public void flush() {
        writer.Flush();
        writer.Close();
    }
    public int boxcounter = 1;
    public int verzweigungstiefe = 1;
    public bool preVisit(Program p) {
        writer.WriteLine("prologues:=3;");
        writer.WriteLine("verbatimtex");
        writer.WriteLine("%&latex");
        writer.WriteLine("\\documentclass{article}");
        writer.WriteLine("\\usepackage{graphics}");
        writer.WriteLine("\\usepackage{color}");
        writer.WriteLine("\\definecolor{dgreen}{rgb}{0.1,0.5,0.1}");
        writer.WriteLine("\\begin{document}");
        writer.WriteLine("etex");
        writer.WriteLine("input expressg;");

        writer.WriteLine("beginfig(1);");
        writer.WriteLine("z0=(0,0);");
        writer.WriteLine("drawovalbox(0,40,17)(btex \\tt start etex);");
        return true;
    }
    public void postVisit(Program p) {
        writer.WriteLine("z" + boxcounter + "=z" + (boxcounter - 1) + "c-(0," + 30 + ");");
        writer.WriteLine("drawovalbox(" + boxcounter + ",40,17)(btex \\tt stop etex);");
        boxcounter++;
        writer.WriteLine("drawnormalCA(" + (boxcounter - 2) + "bm," + (boxcounter - 1) + "tm);");

        writer.WriteLine("endfig;");
        writer.WriteLine("end;");
    }
    public bool preVisit(Stmt.Assign i) {
        String text = " " + i.ToString();
        int length = (text.Length + 1) * 5;
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter - 1) + "c-(0," + 30 + ");");
        writer.WriteLine("drawENT(" + boxcounter++ + "," + length + ",17)(btex \\tt " + text + " etex);");
        writer.WriteLine("drawnormalCA(" + (boxcounter - 2) + "bm," + (boxcounter - 1) + "tm);");
        return true;
    }
    public bool preVisit(Stmt.Write i) {
        String text = i.ToString();
        int length = 5 + (text.Length + 1) * 5;
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter - 1) + "c-(0," + 30 + ");");
        writer.WriteLine("drawLEVENT(" + boxcounter++ + "," + length + ",17)(btex \\tt " + i + " etex);");
        writer.WriteLine("drawnormalCA(" + (boxcounter - 2) + "bm," + (boxcounter - 1) + "tm);");
        return true;
    }
    public void visit(Stmt.Read i) {
        String text = i.ToString();
        int length = 5 + (text.Length + 1) * 5;
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter - 1) + "c-(0," + 30 + ");");
        writer.WriteLine("drawLEVENT(" + boxcounter++ + "," + length + ",17)(btex \\tt " + i + " etex);");
        writer.WriteLine("drawnormalCA(" + (boxcounter - 2) + "bm," + (boxcounter - 1) + "tm);");
    }
    public bool preVisit(Stmt.IfThenElse i) {
        verzweigungstiefe++;
        int spreading = 100 - verzweigungstiefe * 20;
        String text = i.cond.toTexString();
        int length = 10 + (text.Length + 1) * 5;
        int ifhead = boxcounter;
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter - 1) + "c-(0," + 30 + ");");
        writer.WriteLine("drawdiamondbox(" + boxcounter++ + "," + length + ",25)(btex \\tt " + text + " etex);");
        writer.WriteLine("drawnormalCA(" + (boxcounter - 2) + "bm," + (boxcounter - 1) + "tm);");
        writer.WriteLine("z" + boxcounter + "bm=z" + ifhead + "  shifted (" + spreading + ",0);");
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter) + "bm;");
        writer.WriteLine("label(btex {\\color{dgreen}\\tt yes} etex,z" + boxcounter + "c);");
        writer.WriteLine("drawnormal(" + ifhead + "mr," + (boxcounter) + "bm);");
        boxcounter++;
        i.then.accept(this);
        int thenend = boxcounter - 1;
        writer.WriteLine("z" + boxcounter + "bm=z" + ifhead + "  shifted (-" + spreading + ",0);");
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter) + "bm;");
        writer.WriteLine("label(btex {\\color{red}\\tt no} etex,z" + boxcounter + "c);");
        writer.WriteLine("drawnormal(" + ifhead + "ml," + (boxcounter) + "bm);");
        boxcounter++;
        if (i.els != null) i.els.accept(this);
        int elseend = boxcounter - 1;

        writer.WriteLine("z" + boxcounter + "=1/2[z" + thenend + "c,z" + elseend + "c] shifted (0,-20);");
        int join = boxcounter;
        boxcounter++;
        //        writer.WriteLine("drawnormal("+thenend+"bm,"+(boxcounter-2)+"c);");
        //        writer.WriteLine("drawnormal("+(boxcounter-4)+"bm,"+(boxcounter-3)+"c);");

        writer.WriteLine("z" + boxcounter + "=(x" + thenend + "c,y" + join + ") shifted(0,-40);");
        boxcounter++;
        writer.WriteLine("z" + boxcounter + "=(x" + elseend + "c,y" + join + ") shifted(0,-40);");
        boxcounter++;

        //	writer.WriteLine("z"+boxcounter+"bm=(x"+ifhead+",min(y"+thenend+",y"+join+"));");
        //	writer.WriteLine("z"+boxcounter+"c=(x"+ifhead+",y"+(boxcounter)+"bm);");
        writer.WriteLine("z" + boxcounter + "=z" + join + " shifted(0,-40);");
        writer.WriteLine("z" + boxcounter + "c=z" + join + " shifted(0,-50);");
        writer.WriteLine("z" + boxcounter + "bm=z" + boxcounter + ";");

        writer.WriteLine("drawnormalthree(" + thenend + "bm," + (boxcounter - 2) + "," + (boxcounter) + ");");
        writer.WriteLine("drawnormalthree(" + elseend + "bm," + (boxcounter - 1) + "," + (boxcounter) + ");");
        boxcounter++;
        //writer.WriteLine("z"+boxcounter+"c="+(boxcounter-1)+";");
        verzweigungstiefe--;
        return false;
    }
    public bool preVisit(Stmt.Loop i) {
        verzweigungstiefe++;
        int spreading = 100 - verzweigungstiefe * 20;
        String text = i.cond.toTexString();
        int length = 10 + (text.Length + 1) * 5;
        int loophead = boxcounter;
        writer.WriteLine("z" + boxcounter + "=z" + (boxcounter - 1) + "c-(0," + 30 + ");");
        writer.WriteLine("drawdiamondbox(" + boxcounter++ + "," + length + ",25)(btex \\tt " + text + " etex);");
        writer.WriteLine("drawnormalCA(" + (boxcounter - 2) + "bm," + (boxcounter - 1) + "tm);");
        writer.WriteLine("z" + boxcounter + "bm=z" + (boxcounter - 1) + "  shifted (" + spreading + ",0);");
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter) + "bm;");
        writer.WriteLine("label(btex {\\color{dgreen}\\tt yes} etex,z" + boxcounter + "c);");
        writer.WriteLine("drawnormal(" + (boxcounter - 1) + "mr," + (boxcounter) + "bm);");
        boxcounter++;
        i.body.accept(this);
        writer.WriteLine("z" + boxcounter + "=z" + (boxcounter - 1) + "c shifted (-70,0);");
        writer.WriteLine("drawnormalthreeCA(" + (boxcounter - 1) + "ml," + boxcounter + "," + (loophead) + "bm);");
        boxcounter++;
        writer.WriteLine("z" + boxcounter + "bm=z" + loophead + " shifted (-50,0);");
        writer.WriteLine("z" + boxcounter + "c=z" + (boxcounter) + "bm;");
        writer.WriteLine("drawnormal(" + loophead + "ml," + (boxcounter) + "bm);");
        writer.WriteLine("label(btex {\\color{red}\\tt no} etex,z" + boxcounter + "c);");
        boxcounter++;
        verzweigungstiefe--;
        return false;
    }
}
